/**
 *
 */
package com.honeybees.framework.spring.mvc.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * <dl>
 * <dt><b> 过滤Get请求 </b></dt>
 * <p>
 * <dd>功能描述</dd>
 * </dl>
 * <p>
 * Copyright (C) All rights reserved.
 * </p>
 *
 * @author 李远明
 * @version 2015-11-30 15:05:02
 */
public class ContentTypeFilter implements Filter {

    private String charsetName = "UTF-8";
    private FilterConfig config;

    /**
     * {@inheritDoc}
     *
     * @version 2015年11月30日 下午3:05:30
     */
    // @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.config = filterConfig;
        String charsetName = config.getServletContext().getInitParameter("charset");
        if (charsetName != null && charsetName.trim().length() != 0) {
            this.charsetName = charsetName;
        }
    }

    /**
     * {@inheritDoc}
     *
     * @version 2015年11月30日 下午3:05:30
     */
    // @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        // 设置请求响应字符编码
        request.setCharacterEncoding(charsetName);
        response.setCharacterEncoding(charsetName);

        // 新增加的代码
        HttpServletRequest req = (HttpServletRequest) request;

        // System.out.println("Method: " + req.getMethod());
        if (req.getMethod().equalsIgnoreCase("get")) {
            req = new HttpGetMethodRequestWrapper(req, charsetName);
        }

        // System.out.println("----请求被" + config.getFilterName() + "过滤");
        // 传递给目标servlet或jsp的实际上时包装器对象的引用，而不是原始的HttpServletRequest对象
        chain.doFilter(req, response);

        // System.out.println("----响应被" + config.getFilterName() + "过滤");
    }

    /**
     * {@inheritDoc}
     *
     * @version 2015年11月30日 下午3:05:30
     */
    // @Override
    public void destroy() {
        // System.out.println(config.getFilterName() + "被销毁");
        charsetName = null;
        config = null;
    }

}

/**
 * <dl>
 * <dt><b> 处理HTTP GET请求 </b></dt>
 * <p>
 * <dd>GET请求编码方式和POST请求提交编码方式不同，GET是把数据直接放到url中，浏览器先对中文进行UTF-8编码(一个中文3个字符表示
 * 太长)，继而为了缩短字符又用ISO-8859-1编码后传递给服务器。服务器的doGet方法中要先进行ISO-8859-1解码，再UTF-8解码才能看到中文。</dd>
 * <p>
 * <dd>而POST请求则在浏览器端把数据以UTF-8的形式存储到HTTP的请求体中，不用通过url传输，继而只要
 * request.setCharacterEncoding("UTF-8");通知request以UTF-8形式解码就行，因为request默认以ISO-8859-1进行解码的。</dd>
 * </dl>
 * <p>
 * Copyright (C) All rights reserved.
 * </p>
 *
 * @author 李远明
 * @version 2016-07-26 10:12:58
 * @see org.springframework.web.filter.HiddenHttpMethodFilter.HttpMethodRequestWrapper
 */
class HttpGetMethodRequestWrapper extends HttpServletRequestWrapper {

    private static final String ISO_8859_1 = "ISO-8859-1";
    private static final String UTF_8 = "UTF-8";
    private String charsetName = UTF_8;

    /**
     * @param request
     */
    public HttpGetMethodRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    public HttpGetMethodRequestWrapper(HttpServletRequest request, String charsetName) {
        super(request);
        this.charsetName = charsetName;
    }

    /**
     * <dl>
     * <dt><b> 重写 {@linkplain ServletRequest#getParameter(String) getParameter} 方法
     * </b></dt>
     * <p>
     * <dd>实际上就是调用被包装的请求对象的getParameter方法获得参数，然后再进行编码转换</dd>
     * <p>
     * <dd>request.getParameter("username")</dd>
     * </dl>
     *
     * @version 2015-11-30 15:35:08
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        value = value == null ? null : convert(value);
        return value;
    }

    private String convert(String value) {
        // System.out.println("编码转换之前：" + target);
        value = value.trim();
        try {
            return new String(value.getBytes(ISO_8859_1), charsetName);
        } catch (UnsupportedEncodingException e) {
            return value;
        }
    }

}
